package com.jiangjiang.eshop.schedule.service.impl;

import com.jiangjiang.eshop.customer.dto.ReturnGoodsWorksheetDTO;
import com.jiangjiang.eshop.order.dto.OrderInfoDTO;
import com.jiangjiang.eshop.order.dto.OrderItemDTO;
import com.jiangjiang.eshop.order.service.OrderInfoService;
import com.jiangjiang.eshop.order.service.OrderService;
import com.jiangjiang.eshop.purchase.dto.PurchaseOrderDTO;
import com.jiangjiang.eshop.schedule.builder.SaleDeliveryOrderBuilder;
import com.jiangjiang.eshop.schedule.constant.StockUpdateEvent;
import com.jiangjiang.eshop.wms.convert.PurchaseInputOrderConvert;
import com.jiangjiang.eshop.schedule.convert.ScheduleOrderPickingItemConvert;
import com.jiangjiang.eshop.schedule.convert.ScheduleOrderSendOutDetailConvert;
import com.jiangjiang.eshop.schedule.domain.ScheduleOrderPickingItemEntity;
import com.jiangjiang.eshop.schedule.domain.ScheduleOrderSendOutDetailEntity;
import com.jiangjiang.eshop.schedule.dto.SaleDeliveryScheduleResult;
import com.jiangjiang.eshop.schedule.factory.SaleDeliveryOrderBuilderFactory;
import com.jiangjiang.eshop.schedule.service.SaleDeliveryScheduler;
import com.jiangjiang.eshop.schedule.service.ScheduleOrderPickingItemService;
import com.jiangjiang.eshop.schedule.service.ScheduleOrderSendOutDetailService;
import com.jiangjiang.eshop.schedule.service.ScheduleService;
import com.jiangjiang.eshop.schedule.stock.ScheduleStockUpdater;
import com.jiangjiang.eshop.schedule.stock.ScheduleStockUpdaterFactory;
import com.jiangjiang.eshop.wms.convert.ReturnGoodsInputOrderConvert;
import com.jiangjiang.eshop.wms.dto.*;
import com.jiangjiang.eshop.wms.service.WmsFacadeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.awt.peer.LightweightPeer;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * @ClassName ScheduleFacadeServiceImpl
 * @Description TODO
 * @Author jhw
 * @Date 2021/6/14 14:08
 * @Version 1.0
 **/
@Service
@Slf4j
public class ScheduleServiceImpl implements ScheduleService {
    @Autowired
    private WmsFacadeService wmsService;
    @Autowired
    private PurchaseInputOrderConvert purchaseInputOrderConvert;
    @Autowired
    private SaleDeliveryOrderBuilderFactory saleDeliveryOrderBuilderFactory;
    @Autowired
    private ReturnGoodsInputOrderConvert returnGoodsInputOrderConvert;
    @Autowired
    private SaleDeliveryScheduler saleDeliveryScheduler;
    @Autowired
    private ScheduleOrderPickingItemConvert scheduleOrderPickingItemConvert;
    @Autowired
    private ScheduleOrderPickingItemService scheduleOrderPickingItemService;
    @Autowired
    private ScheduleOrderSendOutDetailConvert scheduleOrderSendOutDetailConvert;
    @Autowired
    private ScheduleOrderSendOutDetailService scheduleOrderSendOutDetailService;
    @Autowired
    private ScheduleStockUpdaterFactory scheduleStockUpdaterFactory;
    @Autowired
    private OrderInfoService orderInfoService;

    @Override
    public Boolean informPurchaseInputFinishedEvent(PurchaseInputOrderDTO purchaseInputOrderDTO) {
        return null;
    }

    @Override
    public Boolean informSubmitOrderEvent(OrderInfoDTO order) {
        try {
            for (OrderItemDTO orderItem : order.getOrderItems()) {
                SaleDeliveryScheduleResult schedule = saleDeliveryScheduler.schedule(orderItem);
                // 批量保存调度拣货明细
                convertPickingItemEntitiesAndSaveBatch(orderItem, schedule);
                // 批量保存调度发货明细
                convertSendOutDetailsAndSaveBatch(orderItem, schedule);
                // 执行调度库存更新
                ScheduleStockUpdater stockUpdater = scheduleStockUpdaterFactory.create(StockUpdateEvent.SUBMIT_ORDER, schedule);
                stockUpdater.update();
                // 通知wms
                wmsService.informSubmitOrderEvent(schedule);
            }

            return true;
        } catch (Exception e) {
            log.warn("ScheduleServiceImpl informSubmitOrderEvent error", e);
            return false;
        }

    }

    private void convertSendOutDetailsAndSaveBatch(OrderItemDTO orderItem, SaleDeliveryScheduleResult schedule) {
        List<ScheduleOrderSendOutDetailEntity> outDetailEntities = scheduleOrderSendOutDetailConvert
                .convertDTOList2Entities(schedule.getSendOutDetails())
                .stream()
                .peek(entity -> {
                    entity.setOrderInfoId(orderItem.getOrderInfoId());
                    entity.setOrderItemId(orderItem.getId());
                }).collect(Collectors.toList());

        scheduleOrderSendOutDetailService.saveBatch(outDetailEntities);
    }

    private void convertPickingItemEntitiesAndSaveBatch(OrderItemDTO orderItem, SaleDeliveryScheduleResult schedule) {
        List<ScheduleOrderPickingItemEntity> pickingItemEntityList = scheduleOrderPickingItemConvert
                .convertDTOList2Entities(schedule.getPickingItems())
                .stream()
                .peek(entity -> {
                    entity.setOrderInfoId(orderItem.getOrderInfoId());
                    entity.setOrderItemId(orderItem.getId());
                })
                .collect(Collectors.toList());

        scheduleOrderPickingItemService.saveBatch(pickingItemEntityList);
    }

    @Override
    public Boolean informPayOrderEvent(OrderInfoDTO orderInfoDTO) {
        return null;
    }

    @Override
    public Boolean informCancelOrderEvent(OrderInfoDTO orderInfoDTO) {
        return null;
    }

    @Override
    public Boolean informReturnGoodsInputFinished(ReturnGoodsInputOrderDTO returnGoodsInputOrderDTO) {
        return null;
    }

    @Override
    public Boolean schedulePurchaseInput(PurchaseOrderDTO purchaseOrderDTO) {
        return wmsService.createPurchaseInputOrder(
                purchaseInputOrderConvert.purchaseOrderConvertPurchaseInputOrder(purchaseOrderDTO)
        );
    }

    @Override
    public Boolean scheduleSaleDelivery(OrderInfoDTO order) {
        try {
            SaleDeliveryOrderBuilder builder = saleDeliveryOrderBuilderFactory.getBuilder();
            SaleDeliveryOrderDTO saleDeliveryOrderDTO = builder.setOrderRelatedData(order)
                    .createSaleDeliveryOrderItems(order.getOrderItems())
                    .createSendOutOrder(order)
                    .createLogisticOrder(order)
                    .initStatus()
                    .initTimes()
                    .create();
            return wmsService.createSaleDeliveryOrder(saleDeliveryOrderDTO);
        } catch (Exception e) {
            log.error("ScheduleServiceImpl scheduleSaleDelivery error", e);
        }
        return false;
    }

    @Override
    public Boolean scheduleReturnGoodsInput(OrderInfoDTO orderInfoDTO, ReturnGoodsWorksheetDTO returnGoodsWorksheetDTO) {
        ReturnGoodsInputOrderDTO returnGoodsInputOrder = returnGoodsInputOrderConvert.convertOrderInfoAndReturnGoodsWorksheet2DTO(orderInfoDTO, returnGoodsWorksheetDTO);
        List<ReturnGoodsInputOrderItemDTO> returnGoodsInputOrderItems = returnGoodsInputOrderConvert.convertOrderItems2InputOrderIntemDTOList(orderInfoDTO.getOrderItems());
        returnGoodsInputOrder.setItems(returnGoodsInputOrderItems);
        return wmsService.createReturnGoodsInputOrder(returnGoodsInputOrder);
    }

    @Override
    public SaleDeliveryScheduleResult getScheduleResult(Long orderInfoId, Long goodsSkuId) {
        try {
            OrderInfoDTO orderInfoDTO = orderInfoService.queryById(orderInfoId);
            Optional<OrderItemDTO> first = orderInfoDTO.getOrderItems()
                    .stream()
                    .filter(item -> item.getGoodsSkuId().equals(goodsSkuId))
                    .findFirst();
            if (first.isPresent()) {
                OrderItemDTO targetOrderItem = first.get();
                return saleDeliveryScheduler.getScheduleResult(targetOrderItem);
            }

        } catch (Exception e) {
            log.warn("ScheduleServiceImpl getScheduleResult error", e);

        }
        return null;
    }
}
